import { GameEvent, SysOrder } from "../../GameDef";
import { ECSEntity } from "../../lib/kgame/ecs/ECSEntity";
import { IECSFilter } from "../../lib/kgame/ecs/ECSFilter";
import { ECSSys } from "../../lib/kgame/ecs/ECSSys";
import { CmpFood } from "../cmp/CmpFood";
import { FoodFactory } from "../factory/FoodFactory";
import { SCmpWorld } from "../scmp/SCmpWorld";

/**
 * 食物系统
 */
export class SysFood extends ECSSys {

    world: SCmpWorld;

    get updateOrder(): number {
        return SysOrder.food;
    }

    get ifilter(): IECSFilter {
        return { includeAll: [CmpFood] };
    }

    protected onStart(): void {
        this.world = this.scene.getCmp(SCmpWorld);
    }

    onDestroy(): void {
        this.world = null;
    }

    protected onEntityAdd(entity: ECSEntity): void {
        const food = entity.getCmp(CmpFood);
        this.world.foodGrid.addItem(food, food.collider.worldAABB);
    }

    protected onEntityRemove(entity: ECSEntity): void {
        const food = entity.getCmp(CmpFood);
        this.world.foodGrid.removeItem(food);
    }

    onUpdate(): void {
        const world = this.scene.getCmp(SCmpWorld);
        const { rand } = this.scene;

        let count = world.foodMax - this.filter.entitySet.size;
        while (--count >= 0) {
            const score = rand.rand() < 0.01 ? rand.range(100, 200) : rand.range(5, 10);
            const spawnPos = world.getRandPos(CmpFood.getSize(score));
            FoodFactory.createFood(this.scene, spawnPos, score);
        }

        if (this.world.eatenFoods.length > 0) {
            this.scene.send(GameEvent.foodEaten, this.world.eatenFoods);
            world.eatenFoods.length = 0;
        }
    }

    protected onUpdateEntity(entity: ECSEntity): void {
        const food = entity.getCmp(CmpFood);
        if (food.lifeTime > -1) {
            food.lifeTime -= this.scene.dt;
            if (food.lifeTime <= 0) {
                food.removeEntity();
            }
        }
    }

}

declare global {
    interface ECSEventData {
        [GameEvent.foodEaten]: readonly kp_entity_eatenFood[]
    }
}